broadway: fix use-after-free on read errors
authorPeter Wu <peter@lekensteyn.nl>
Thu, 23 Jul 2015 15:13:54 +0000 (17:13 +0200)
committerMatthias Clasen <mclasen@redhat.com>
Sun, 26 Jul 2015 04:46:13 +0000 (00:46 -0400)
Call chain:
 - input_data_cb
   - broadway_server_read_all_input_nonblocking (input)
     - broadway_input_free (input)
       (now input is invalid)
     attempt to use input->active -> use-after-free

Make broadway_server_read_all_input_nonblocking return a boolean, TRUE
if the input was valid, FALSE otherwise. This allows input_data_cb to
detect whether the input was gone or not.

https://bugzilla.gnome.org/show_bug.cgi?id=741685

gdk/broadway/broadway-server.c

index 42bc50a43af94f1c24078b7905b04eb324903b9e..9e659fff18827dc021cf988696b5afe80c77c3f7 100644 (file)
@@ -661,7 +661,7 @@ queue_process_input_at_idle (BroadwayServer *server)
       g_idle_add_full (G_PRIORITY_DEFAULT, (GSourceFunc)process_input_idle_cb, server, NULL);
 }
 
-static void
+static gboolean
 broadway_server_read_all_input_nonblocking (BroadwayInput *input)
 {
   GInputStream *in;
@@ -670,7 +670,7 @@ broadway_server_read_all_input_nonblocking (BroadwayInput *input)
   GError *error = NULL;
 
   if (input == NULL)
-    return;
+    return FALSE;
 
   in = g_io_stream_get_input_stream (input->connection);
 
@@ -683,7 +683,7 @@ broadway_server_read_all_input_nonblocking (BroadwayInput *input)
          g_error_matches (error, G_IO_ERROR, G_IO_ERROR_WOULD_BLOCK))
        {
          g_error_free (error);
-         return;
+         return TRUE;
        }
 
       if (input->server->input == input)
@@ -694,12 +694,13 @@ broadway_server_read_all_input_nonblocking (BroadwayInput *input)
          g_printerr ("input error %s\n", error->message);
          g_error_free (error);
        }
-      return;
+      return FALSE;
     }
 
   g_byte_array_append (input->buffer, buffer, res);
 
   parse_input (input);
+  return TRUE;
 }
 
 static void
@@ -720,7 +721,8 @@ input_data_cb (GObject  *stream,
 {
   BroadwayServer *server = input->server;
 
-  broadway_server_read_all_input_nonblocking (input);
+  if (!broadway_server_read_all_input_nonblocking (input))
+    return FALSE;
 
   if (input->active)
     process_input_messages (server);